package paasio

import (
	"io"
	"sync"
)

const testVersion = 3

type MyCounter struct {
	n      int64
	nops   int
	rwlock sync.RWMutex
}

func (c *MyCounter) getCount() (int64, int) {
	c.rwlock.RLock()
	defer c.rwlock.RUnlock()
	return c.n, c.nops
}

func (c *MyCounter) setCount(r int) {
	c.rwlock.Lock()
	defer c.rwlock.Unlock()
	c.n += int64(r)
	c.nops++
}

type MyReadCounter struct {
	r io.Reader
	c MyCounter
}

func (rc *MyReadCounter) ReadCount() (n int64, nops int) {
	n, nops = rc.c.getCount()
	return
}

func (rc *MyReadCounter) Read(p []byte) (r int, err error) {
	r, err = rc.r.Read(p)
	rc.c.setCount(r)
	return
}

type MyWriteCounter struct {
	w io.Writer
	c MyCounter
}

func (wc *MyWriteCounter) WriteCount() (n int64, nops int) {
	n, nops = wc.c.getCount()
	return
}

func (wc *MyWriteCounter) Write(p []byte) (n int, err error) {
	n, err = wc.w.Write(p)
	wc.c.setCount(n)
	return
}

type MyReadWriteCounter struct {
	rc MyReadCounter
	wc MyWriteCounter
}

func (rwc *MyReadWriteCounter) ReadCount() (n int64, nops int) {
	n, nops = rwc.rc.ReadCount()
	return
}

func (rwc *MyReadWriteCounter) Read(p []byte) (r int, err error) {
	r, err = rwc.rc.Read(p)
	return
}

func (rwc *MyReadWriteCounter) WriteCount() (n int64, nops int) {
	n, nops = rwc.wc.WriteCount()
	return
}

func (rwc *MyReadWriteCounter) Write(p []byte) (n int, err error) {
	n, err = rwc.wc.Write(p)
	return
}

func NewReadCounter(r io.Reader) ReadCounter {
	return &MyReadCounter{r: r}
}

func NewWriteCounter(w io.Writer) WriteCounter {
	return &MyWriteCounter{w: w}
}

func NewReadWriteCounter(wr io.ReadWriter) ReadWriteCounter {
	return &MyReadWriteCounter{
		MyReadCounter{r: wr},
		MyWriteCounter{w: wr},
	}
}
